const { ccclass, property } = cc._decorator;

enum Time {
    touchstart = 1,
    touchmove = 2,
    touchend = 3,
    touchcancel = 4,
    click = 5
}

@ccclass
export default abstract class BaseButtonTouch extends cc.Component {
    @property
    protected _target: cc.Node = null;
    @property(cc.Node)
    get target() {
        if (this._target && !this._target.isValid) {
            this._target = null;
        }
        return this._target || this.node;
    }
    set target(value) {
        const oldValue = this.target;
        this._target = value;
        if (oldValue !== this.target) {
            oldValue.removeComponent(cc.Button);
        }
        this.resetButton();
    }

    @property({
        visible: false
    })
    protected timeEvent: string = 'click';

    @property
    protected _time: Time = Time.click;
    @property({ type: cc.Enum(Time) })
    get time() { return this._time; }
    set time(value) {
        this._time = value;
        this.timeEvent = Time[this.time];
        this.resetButton();
    }
    /**
     * !#en Color and Scale transition duration
     * !#zh 颜色过渡和缩放过渡时所需时间
     * @property {Number} duration
     */
    @property
    protected _duration: number = 0.1;
    @property({
        range: [0, 10],
        tooltip: CC_DEV && 'i18n:COMPONENT.button.duration',
        visible(this: BaseButtonTouch) {
            return this.time === Time.click;
        }
    })
    get duration() { return this._duration; }
    set duration(value) {
        this._duration = value;
        this.resetButton();
    }
    /**
     * !#en  When user press the button, the button will zoom to a scale.
     * The final scale of the button  equals (button original scale * zoomScale)
     * !#zh 当用户点击按钮后，按钮会缩放到一个值，这个值等于 Button 原始 scale * zoomScale
     * @property {Number} zoomScale
     */
    @property()
    protected _zoomScale: number = 0.8;
    @property({
        tooltip: CC_DEV && 'i18n:COMPONENT.button.zoom_scale',
        visible(this: BaseButtonTouch) {
            return this.time === Time.click;
        }
    })
    get zoomScale() { return this._zoomScale; }
    set zoomScale(value) {
        this._zoomScale = value;
        this.resetButton();
    }

    /**
     * !#en
     * Whether the Button is disabled.
     * If true, the Button will trigger event and do transition.
     * !#zh
     * 按钮事件是否被响应，如果为 false，则按钮将被禁用。
     * @property {Boolean} interactable
     * @default true
     */
    @property()
    protected _interactable: boolean = true;
    @property({
        tooltip: CC_DEV && 'i18n:COMPONENT.button.interactable',
        visible(this: BaseButtonTouch) {
            return this.time === Time.click;
        }
    })
    get interactable() { return this._interactable; }
    set interactable(value) {
        this._interactable = value;
        this.resetButton();
    }

    /**
     * !#en When this flag is true, Button target sprite will turn gray when interactable is false.
     * !#zh 如果这个标记为 true，当 button 的 interactable 属性为 false 的时候，会使用内置 shader 让 button 的 target 节点的 sprite 组件变灰
     * @property {Boolean} enableAutoGrayEffect
     */
    @property()
    protected _enableAutoGrayEffect: boolean = false;
    @property({
        tooltip: CC_DEV && 'i18n:COMPONENT.button.auto_gray_effect',
        visible(this: BaseButtonTouch) {
            return this.time === Time.click;
        }
    })
    get enableAutoGrayEffect() { return this._enableAutoGrayEffect; }
    set enableAutoGrayEffect(value) {
        this._interactable = value;
        this.resetButton();
    }

    start() {
        this.resetButton();
    }

    private resetButton() {
        if (CC_EDITOR) return;
        const node = this.target || this.node;
        if (this.time === Time.click) {
            let btn = node.getComponent(cc.Button);
            if (!btn) {
                btn = node.addComponent(cc.Button);
                btn.transition = cc.Button.Transition.SCALE;
            }
            btn.interactable = this.interactable;
            btn.enableAutoGrayEffect = this.enableAutoGrayEffect;
            btn.duration = this.duration;
            btn.zoomScale = this.zoomScale;
        } else {
            node.removeComponent(cc.Button);
        }
    }
}
